#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Filename: create_ticket.py

##
# Módulos del sistema
# Parte gráfica
try:
    import pygtk
    pygtk.require("2.0")
    import gtk
    import gtk.glade
except ImportError, error:
    print error
    print "Necesitas la librería gráficas gtk+pygtk"

##
# Utilidades
import os
from datetime import datetime

##
# Módulos propios
try:
    from lib.database import EmpleadoBD, ClasificacionBD, GrupoDeResolucionBD
except ImportError, error:
    print error
    print "Problemas con la BD"
try:
    from lib.config import WIDTH, HEIGHT
    from lib.empleado import Empleado
    from lib.grupo_de_resolucion import Clasificacion
    from gui.msj_retroalimentacion import MensajeDeAdvertencia, MensajeDeError
except ImportError, error:
    print error
    print "No se pudo cargar el archivo (create_ticket.py)"

class CreateTicket:
    """Crear ticket.

    Clase que permitira el manejo de la interfaz de creación de ticket.
    Utilizado en el CDU-01 Registrar Ticket

    """
    def __init__(self, padre, usuario_logueado):
        self.gladefile = "gui/ghhp.glade"
        self.wTree = gtk.glade.XML(self.gladefile,"create_ticket")
        self.window = self.wTree.get_widget("create_ticket")
        self.window.resize(WIDTH,HEIGHT)
        self.hbox_62 = self.wTree.get_widget("hbox62")
        self.hbox_64 = self.wTree.get_widget("hbox64")
        self.hbox_65 = self.wTree.get_widget("hbox65")
        self.hbox_156 = self.wTree.get_widget("hbox156")
        self.entry_legajo_empleado = self.wTree.get_widget("entry70")
        self.entry_apellido_empleado = self.wTree.get_widget("entry71")
        self.entry_nombre_empleado = self.wTree.get_widget("entry72")
        self.entry_codigo_clasificacion = self.wTree.get_widget("entry73")
        self.entry_nombre_clasificacion = self.wTree.get_widget("entry74")
        self.entry_descripcion = self.wTree.get_widget("textview6")
        ##
        # Acá iria una funcion que busque en la BD el siguiente numero de
        # ticket
        self.wTree.get_widget("label_numero_ticket").set_text('FIXME')
        self.un_dict={"on_button37_clicked": self.validate_create_ticket,
                "on_button38_clicked": self.close,
                "on_button41_clicked": self.derivar_ticket,
                "on_button40_clicked": self.close_ticket,
                "on_button111_clicked": self.close,
                "on_button110_clicked": self.validate_derivar_ticket}
        self.wTree.signal_autoconnect(self.un_dict)

        ##
        # Requerimiento especial del CDU. Con <Enter> pasamos de entry
        self.conect_entry_enter()

        ##
        # Agregamos fecha y hora actual
        #self.fecha,self.hora = datetime.today().isoformat()[:-7].split('T')
        self.fecha_creacion = datetime.now()
        self.fecha, self.hora = self.fecha_creacion.strftime("%Y:%m:%d %H:%M:%S").split()
        self.wTree.get_widget("label_fecha_apertura").set_text(self.fecha)
        self.wTree.get_widget("label_hora_apertura").set_text(self.hora)

        ##
        # Variables necesarias para registrar ticket   
        self.padre = padre
        self.empleado_solicitante = None 
        self.usuario_logueado = usuario_logueado
        self.clasificacion_problema = None
        #self.numero = 

    def conect_entry_enter(self):
        """Permite generar the activate signal para los widget"""
        def grab_focus(widget, other):
            other.grab_focus()
            self.completar_campos()

        def groups(lista, n, step=1):
            for index in xrange(0, len(lista)-(n-1), step):
                yield lista[index:index+n]

        path =(self.entry_legajo_empleado,
                self.entry_apellido_empleado,
                self.entry_nombre_empleado,
                self.entry_codigo_clasificacion,
                self.entry_nombre_clasificacion,
                self.entry_descripcion)

        for from0, to in groups(path, 2):
            from0.connect("activate", grab_focus, to)

    def completar_campos(self):
        """Completará los campos de entrada.

        Busca en la base de datos el nombre y apellido del Empleado con legago
        "nro_legajo" y la Clasificación con "nro_clasificacion", y los muestro
        en los campos correspondientes luedo de presionar <Enter> desde la
        funcion conect_entry_enter.

        Keyword arguments:
        None
        """
        nro_legajo = self.entry_legajo_empleado.get_text()
        nro_clasificacion = self.entry_codigo_clasificacion.get_text()

        if nro_legajo != '':
            # Levantar el apellido y nombre con este legajo
            consulta = EmpleadoBD.selectBy(legajo = nro_legajo)
            try:
                empleado = consulta[0]
                self.entry_apellido_empleado.set_text(empleado.apellido)
                self.entry_nombre_empleado.set_text(empleado.nombre)
                self.empleado_solicitante = Empleado(empleado)
                self.entry_codigo_clasificacion.grab_focus()
            except IndexError, error:
                print error
                msj = "Nro. de legajo inexistente en el Sistema de Personal."
                print msj
                msj_error = MensajeDeError(msj, self.window)
                msj_error.run()
                self.entry_legajo_empleado.set_text('')
                self.entry_legajo_empleado.grab_focus()
        if nro_clasificacion !='':
            # Levantar el nombre de este codigo de clasificacion
            consulta = ClasificacionBD.selectBy(id = nro_clasificacion)
            try:
                clasificacion = consulta[0]
                self.entry_nombre_clasificacion.set_text(clasificacion.nombre)
                self.clasificacion_problema = Clasificacion(clasificacion)
                self.entry_descripcion.grab_focus()
            except IndexError, error:
                print error
                msj = "Codigo de clasificacion inexistente en el Sistema."
                print msj
                msj_error = MensajeDeError(msj, self.window)
                msj_error.run()
                self.entry_codigo_clasificacion.set_text('')
        if (nro_legajo == '' and
                self.entry_apellido_empleado.get_text() !='' and
                self.entry_nombre_empleado.get_text()):
            consulta = EmpleadoBD.selectBy(
                    apellido = self.entry_apellido_empleado.get_text(),
                    nombre = self.entry_nombre_empleado.get_text())
            try:
                empleado = consulta[0]
                entry_legajo_empleado.set_text(empleado.legajo)
                self.empleado_solicitante = Empleado(empleado)
                print self.empleado_solicitante
            except IndexError, error:
                print error
                msj = "Empleado inexistente en el Sistema de Personal."
                msj_error = MensajeDeError(msj, self.window)
                msj_error.run()
                self.entry_legajo_empleado.set_text('')
                self.entry_apellido_empleado.set_text('')
                self.entry_nombre_empleado.set_text('')
                self.entry_legajo_empleado.grab_focus()

    def run(self):
        #self.w_create_ticket = self.wTree.get_widget("create_ticket")
        #gtk.main()
        pass

    def datos_no_validos(self):
        """Valida los datos de entrada para CREAR TICKET.

        Comprueba todos lo campos obligatorios necesarios para completar esta
        actividad, ellos son:
        -Legajo
        -Clasificacion
        -Descripcion del problema-

        Keyword arguments:
        None
        """
        if (self.entry_legajo_empleado.get_text() == "" or
               self.entry_codigo_clasificacion.get_text() == "" or
               self.texto_descripcion == "" ):
            #Caso 1
            error = "- Legajo\n- Clasificacion\n- Observaciones\n No pueden ser nulos"
            return True, error
        else:
            #Caso2:
            return False, ""

    def validate_create_ticket(self, widget):
        """Llama a datos_no_validos.

        Dependiendo de lo que retorna datos_no_validos mostrará la informacion
        necesaria para la proxima actividad -cerrar ó derivar-

        Keyword arguments:
        widget -- Widget de crear ticket

        """
        descripcion = self.wTree.get_widget("textview6").get_buffer()
        start = descripcion.get_start_iter()
        end = descripcion.get_end_iter()
        self.texto_descripcion = descripcion.get_text(start,end)

        datos_no_validos,error = self.datos_no_validos()
        if datos_no_validos:
            msj_error = MensajeDeError(error, self.window)
            msj_error.run()
        else:
            # Sistema registra el ticket como "abierto en mesa de ayuda"
            # !!! FIXME :al tener simultaneidad no se si deberia ser un pop(),
            # sino que deberiamos buscarlo por el numero. Lo solucione haciendo
            # que el mismo constructor me devuelva la posicion en la cual fue
            # agregado, asi solo resta con buscar.

            self.pos = self.padre.mesa_de_ayuda.crearTicket(
                            self.padre.usuario_logueado,
                            self.empleado_solicitante,
                            self.clasificacion_problema,
                            self.texto_descripcion,
                            self.fecha_creacion)
            #import pdb
            #pdb.set_trace()
            self.hbox_62.hide()
            # Se deben mostrar en el hbox64 los datos que pide la
            # especificacion del caso de uso nro_1
            self.wTree.get_widget("legajo_cliente").set_text(
                    self.empleado_solicitante.legajo)
            self.wTree.get_widget("apellido_cliente").set_text(
                    self.empleado_solicitante.apellido)
            self.wTree.get_widget("nombre_cliente").set_text(
                    self.empleado_solicitante.nombre)
            self.wTree.get_widget("codigo_clasificacion").set_text(
                    str(self.clasificacion_problema.codigo))
            self.wTree.get_widget("nombre_clasificacion").set_text(
                    self.clasificacion_problema.nombre)
            self.wTree.get_widget("numero_ticket").set_text(
                    str(self.padre.mesa_de_ayuda.tickets[self.pos-1].numero))
            self.wTree.get_widget("descripcion_problema").set_text(self.texto_descripcion)
            self.wTree.get_widget("label271").set_text(self.fecha)
            self.wTree.get_widget("label272").set_text(self.hora)
            self.hbox_65.show()
            self.wTree.get_widget("textview9").grab_focus()
            self.hbox_64.show()

    def derivar_ticket(self, widget):
        """Deriva el ticket al grupo de resolucion que selecciona el usuario.

        Tenemos que validar observacion y ademas hacer hbox49 show() que ahí se
        encuentra la informacion de los grupos de resolucion. Datos necesarios
        para la derivacion de ticket.

        """
        self.wTree.get_widget("vbox49").show()
        self.hbox_156.hide()
        self.obs, bandera = self.observacion_valida()
        if bandera:
            self.armar_lista_de_grupos()

    def validate_derivar_ticket(self, widget):
        """
        """
        grupo, seleccionado = self.un_grupo_seleccionado()
        if seleccionado:
            texto = "¿Está seguro que desea derivar el reclamo?"
            msj = MensajeDeAdvertencia(texto, self.window)
            if msj.msj.run() == gtk.RESPONSE_YES:
                print self.lista_grupos[grupo]
                # Derivamos ticket
                fecha_derivacion = datetime.now()

                self.padre.mesa_de_ayuda.derivarTicket(self.lista_grupos[grupo],
                        fecha_derivacion,
                        self.obs,
                        self.padre.usuario_logueado,
                        self.pos)
                self.window.destroy()
            else:
                msj.msj.destroy()
        else:
            texto = "Debe seleccionar el Grupo al cual se derivará el ticket."
            msj = MensajeDeError(texto, self.window)
            msj.run()

    def un_grupo_seleccionado(self):
        """Permite comprobar si selecciono un grupo de la lista.


        """
        model, path = self.list_view_grupos.get_selection().get_selected_rows()
        if path:
            import pdb
            pos, = path[0]
            return pos, True
        else:
            return "", False

    def armar_lista_de_grupos(self):
        """Permite completra el treeview31 con los grupos habilidatos."""
        self.lista_grupos = []
        resultado = GrupoDeResolucionBD.select()
        for grupo in resultado:
            if self.clasificacion_problema.clasificacion_BD in grupo.clasificaciones:
                self.lista_grupos.append(grupo)
        # Armamos las cabeceras de la lista de grupos
        self.list_view_grupos = self.wTree.get_widget("treeview31")
        self.add_find_column("Numero", 0)
        self.add_find_column("Nombre", 1)
        self.find_list = gtk.ListStore(str, str)
        self.list_view_grupos.set_model(self.find_list)
        # Completamos con los grupos
        for grupo in self.lista_grupos:
            self.find_list.append([str(grupo.id), grupo.nombre])

    def add_find_column(self, title, columnId):
        """Agrega una columna al la lista de grupos habilitados.

        Keyword arguments:
        title -- Título de la columna
        columnId -- posicion donde queremos la columna
        """
        column = gtk.TreeViewColumn(title, gtk.CellRendererText(),
                text=columnId)
        column.set_resizable(True)
        column.set_sort_column_id(columnId)
        self.list_view_grupos.append_column(column)

    def observacion_valida(self):
        """Valida el campo Observaciones.

        Este campo es un dato obligatorio, tanto para la derivacion como para
        el cierre de un reclamo.

        Keyword arguments:
        None
        """
        obs = self.wTree.get_widget("textview9").get_buffer()
        start = obs.get_start_iter()
        end = obs.get_end_iter()
        if obs.get_text(start, end) != "":
            return obs.get_text(start, end), True
        else:
            msj = "Observacion no puede ser nulo en esta operacion."
            print msj
            msj_error = MensajeDeError(msj, self.window)
            msj_error.run()
            return "", False

    def close_ticket(self, widget):
        """CDU03 Cerrar ticket.

        Cerrará el ticket almacenando la fecha y hora actual.
        """
        obs, bandera = self.observacion_valida()
        if bandera:
            texto = "¿Está seguro que desea cerrar el reclamo?"
            msj = MensajeDeAdvertencia(texto, self.window)
            if msj.msj.run() == gtk.RESPONSE_YES:
                print "Cerrando reclamo..."
                fecha_cierre = datetime.now()
                self.padre.mesa_de_ayuda.cerrarTicket(self.padre.usuario_logueado,
                        obs,
                        fecha_cierre,
                        self.pos-1)
                self.window.destroy()
            else:
                msj.msj.destroy()

    def close(self, widget):
        """Cancelación de la operación.

        Se mostrará un mensaje de retroalimentación de advertencia, para
        consultar al usuario si realmente es lo que desea.
        """
        print "Operacion de registro de ticket fue cancelada"
        texto = "¿Esta seguro que desea cancelar la operación?"
        msj = MensajeDeAdvertencia(texto, self.window)
        if msj.msj.run() == gtk.RESPONSE_YES:
            self.window.destroy()
        else:
            "No quiero cancelar la operacion."
            msj.msj.destroy()
